package ch.epfl.lara.pm.global;

import ch.epfl.lara.pm.ast._

import scala.collection.mutable.HashMap


/**
 * The object table contains the list of declared object in the source program.  
 * In our mini-scala language object definition are allowed (and must) to contains only
 * the extractor definition.
 */
object ObjectTable {
  
  private val otable = new HashMap[String,ObjectDef]
  
  /**
   * <p>
   *    Add a new entry to the object table. Print a error mesage if the entry already exist.
   * </p>
   */
  def addEntry(obj: ObjectDef) = otable.contains(obj.name) match {
    case false => otable + ((obj.name,obj))
    case true => error("Error: Object "+obj.name+" is already defined in the scope") 
  }
  
   /**
    * <p>
    *    Retrieve the object definition if the name key exists in the table.
    *    Issue an error message if the entry does not exist.
    * </p>
    */
  def lookupObject(name: String): ObjectDef = otable.get(name) match {
    case None => error("Error: Object "+name+" is not defined in the scope")
      
    case Some(obj) => obj
  }
  
  def containsObject(name: String): Boolean = otable.contains(name)
    
  /**
   * <p>
   *     Retrieve the extractor declaration by accessing the correspondant object declaration.
   *     Issue an error message if the object name key does not exist in the object table.
   * </p>
   */  
  def getExtractor(name: String) = {
     lookupObject(name).extractor
  }
   
  
  def getExtractorType(name: String): TypeTree = getExtractor(name).getParamtype
   
   
  def getExtractorFieldsType(name: String) = getExtractor(name).tpe match {
    case OptionType(xs) => xs
    case tpe @ _ => tpe :: Nil 
  }
  
  def getExtractorNames = otable.keys.toList
  
  /**
   * <p>
   *    Remove all mappings from the object table.
   * </p>
   */
  def clean = otable.clear
   
}
